﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NGourd.Core.Reports;
using NGourd.Core;

namespace NGourd
{
    class ConsoleReporter : IReporter
    {
        public void PrintReport(ReportNode root)
        {
            root.UpdateStatus();
            PrintReport(root, 0);
            PrintStats(root);
        }

        private void PrintStats(ReportNode root)
        {
            Console.WriteLine();
            WriteStats(root, ReportTarget.FEATURE, "Features");
            WriteStats(root, ReportTarget.SCENARIO, "Scenarios");
            WriteStats(root, ReportTarget.STEP, "Steps");
        }

        private void WriteStats(ReportNode root, ReportTarget target, string text)
        {
            var nodes = root.Flatten().Where(n => n.TargetType == target);

            Console.Write(text + ": ");
            WriteStats(nodes, ReportStatus.PASSED, "passed");
            WriteStats(nodes, ReportStatus.FAILED, "failed");
            WriteStats(nodes, ReportStatus.SKIPPED, "skipped");
            WriteStats(nodes, ReportStatus.INCONCLUSIVE, "not found");
            Console.WriteLine();
        }

        private void WriteStats(IEnumerable<ReportNode> nodes, ReportStatus status, string text)
        {
            WriteWithColor(nodes.Count(n => n.Status == status) + " " + text + " ", ConvertStatusToColor(status));
        }

        private void WriteWithColor<T>(T item, ConsoleColor color)
        {
            using( new ConsoleColorer(color))
            {
                Console.Write(item);
            }
        }

        protected void PrintReport(ReportNode root, int tabDepth)
        {
            var color = ConvertStatusToColor(root.Status);
            using (new ConsoleColorer(color))
            {
                for (int i = 0; i < tabDepth; i++)
                    Console.Write("  ");
                Console.WriteLine("{0} {1}", ShortStatus(root.Status), root.Text);
                if (root.Status == ReportStatus.PASSED && root.TargetType == ReportTarget.SCENARIO)
                    return;
                foreach (var child in root.Nodes)
                    PrintReport(child, tabDepth + 1);
            }
        }

        private ConsoleColor ConvertStatusToColor(ReportStatus reportStatus)
        {
            switch (reportStatus)
            {
                case ReportStatus.UNKNOWN:
                    return ConsoleColor.Magenta;
                case ReportStatus.FAILED:
                    return ConsoleColor.Red;
                case ReportStatus.PASSED:
                    return ConsoleColor.Green;
                case ReportStatus.SKIPPED:
                    return ConsoleColor.Cyan;
                case ReportStatus.INCONCLUSIVE:
                    return ConsoleColor.Yellow;
                default:
                    return ConsoleColor.Cyan;
            }
        }

        private string ShortStatus(ReportStatus reportStatus)
        {
            switch (reportStatus)
            {
                case ReportStatus.UNKNOWN:
                    return "!";
                case ReportStatus.PASSED:
                    return ".";
                case ReportStatus.SKIPPED:
                    return "S";
                case ReportStatus.FAILED:
                    return "F";
                case ReportStatus.INCONCLUSIVE:
                    return "?";
                default:
                    return "";
            }
        }
    }
}
